/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.XPath;

namespace DaveSexton.DocProject.Sandcastle.ContentManagement
{
	[Flags]
	public enum ContentItemEditModes
	{
		None = 0,
		Source = 1,
		Design = 2
	}

	[Serializable]
	public class ContentItem
	{
		#region Public Properties
		public virtual string Name
		{
			get
			{
				return name;
			}
			protected set
			{
				if (!string.Equals(name, value, StringComparison.Ordinal))
				{
					name = value;
					dirty = true;

					if (document != null)
						document.NotifyItemChanged(this);
				}
			}
		}

		public virtual string Value
		{
			get
			{
				return _value ?? string.Empty;
			}
			set
			{
				if ((editModes & ContentItemEditModes.Source) == 0 && (editModes & ContentItemEditModes.Design) == 0)
					throw new InvalidOperationException(string.Format(System.Globalization.CultureInfo.CurrentCulture,
						Resources.Errors.ContentItemNotEditable, name));

				System.Diagnostics.Debug.WriteLine("Value assigned for content item: " + Name + "; Current value length = " + ((_value == null) ? 0 : _value.Length));

				if ((_value != null || value != null) && !string.Equals(_value ?? "", value, StringComparison.Ordinal))
				{
					System.Diagnostics.Debug.WriteLine("Value committed for content item: " + Name + "; New value length = " + ((value == null) ? 0 : value.Length));

					_value = value;
					dirty = true;

					if (document != null)
						document.NotifyItemChanged(this);
				}
			}
		}

		public virtual bool IsDirty
		{
			get
			{
				return dirty;
			}
			protected internal set
			{
				dirty = value;
			}
		}

		public virtual bool IsValueDesignable
		{
			get
			{
				return (editModes & ContentItemEditModes.Design) == ContentItemEditModes.Design;
			}
		}

		public virtual bool IsValueEditable
		{
			get
			{
				return (editModes & ContentItemEditModes.Design) == ContentItemEditModes.Design
					|| (editModes & ContentItemEditModes.Source) == ContentItemEditModes.Source;
			}
		}

		public virtual ContentItemEditModes EditModes
		{
			get
			{
				return editModes;
			}
			protected set
			{
				editModes = value;
			}
		}

		public virtual ICollection<string> Subsections
		{
			get
			{
				return null;
			}
		}

		public virtual bool Multiple
		{
			get
			{
				return false;
			}
		}

		public virtual ContentItemAttributeDataCollection Attributes
		{
			get
			{
				return null;
			}
		}

		public virtual bool ShowAttributes
		{
			get
			{
				return false;
			}
		}

		public virtual bool CanEditAttributes
		{
			get
			{
				return false;
			}
		}

		public virtual bool CanEditAttributeValues
		{
			get
			{
				return true;
			}
		}

		public virtual bool IsVisible
		{
			get
			{
				return true;
			}
		}

		public ContentDocument Document
		{
			get
			{
				return document;
			}
			internal set
			{
				// NOTE: value may be null
				document = value;
			}
		}
		#endregion

		#region Private / Protected
		private ContentDocument document;
		private string name;
		private ContentItemEditModes editModes;
		private string _value;
		private bool dirty;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="ContentItem" /> class for derived classes.
		/// </summary>
		protected ContentItem()
		{
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="ContentItem" /> class.
		/// </summary>
		public ContentItem(string name, bool designable)
		{
			if (string.IsNullOrEmpty(name))
				throw new ArgumentException(Resources.Errors.NullOrEmpty, "name");

			this.name = name;
			
			editModes = ContentItemEditModes.Source;

			if (designable)
				editModes |= ContentItemEditModes.Design;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="ContentItem" /> class.
		/// </summary>
		public ContentItem(string name, ContentItemEditModes editModes)
		{
			if (string.IsNullOrEmpty(name))
				throw new ArgumentException(Resources.Errors.NullOrEmpty, "name");

			this.name = name;
			this.editModes = editModes;
		}
		#endregion

		#region Methods
		public virtual bool Delete()
		{
			return false;
		}

		public override string ToString()
		{
			return name;
		}

		protected internal virtual void NotifyAttributeChanged(ContentItemAttributeData attribute)
		{
			dirty = true;

			if (document != null)
				document.NotifyItemChanged(this);
		}
		#endregion
	}
}
